/*********************************************************************************
 *      Copyright:  (C) 2025 LingYun IoT System Studio
 *                  All rights reserved.
 *
 *       Filename:  ds18b20_get_temp.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(26/03/25)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "26/03/25 21:26:15"
 *                 
 ********************************************************************************/

#include "ds18b20_get.h"
#include "struct.h"

int get_temper(data_t *data)
{
	int             fd = -1;
	char            buf[128];
	char            *ptr = NULL;
	DIR             *dirp = NULL;
	struct dirent   *direntp = NULL;
	char            w1_path[64] = "/sys/bus/w1/devices/";
	char            chip_sn[32];
	int             found = 0;

	if( !data )
	{
		log_error("ERROR: Invalid input arguments\n");
		return -1;
	}

	dirp = opendir(w1_path);
	if(!dirp)
	{
		log_error("open file %s failure: %s\n",w1_path, strerror(errno));
		return -2;
	}

	while(NULL != (direntp = readdir(dirp)))
	{
		if(strstr(direntp->d_name,"28-"))
		{
			strncpy(chip_sn, direntp->d_name, sizeof(chip_sn));
			found = 1;
			break;
		}
	}
	closedir(dirp);

	if( !found )
	{
		log_error("Can not find ds18b20 chipset\n");
		return -2;
	}

	strncat(w1_path, chip_sn, sizeof(w1_path)-strlen(w1_path));
	strncat(w1_path, "/w1_slave", sizeof(w1_path)-strlen(w1_path));

	if( (fd =open(w1_path,O_RDONLY)) < 0 )
	{
		log_error("open file failure: %s\n",strerror(errno));
		return -2;
	}

	memset(buf, 0, sizeof(buf));

	if(read(fd, buf, sizeof(buf)) < 0)
	{
		log_error("read data from fd = %d failure %s\n", fd, strerror(errno));
		close(fd);
		return -2;
	}

	ptr = strstr(buf, "t=");
	if( !ptr )
	{
		log_error("Can not find t= string\n");
		close(fd);
		return -2;
	}

	ptr = strstr(buf, "t=");
	if( !ptr )
	{
		log_error("ERROR: Can not get temperature\n");
		close(fd);
		return -2;
	}

	ptr += 2;

	data->temper = atoi(ptr)/1000;

	close(fd);
	return 0;
}

/*获取序列号 */
void get_sn(char *id, int len, int sn)
{
	memset(id, 0, len);
	snprintf(id, len, "rpi%04d", sn);
	return ;
}

/*获取时间*/
long get_time(data_t *data)
{
	time_t      now;
	struct tm   *t;
	long        times;
	int         result;
	int         len;

	now = time(NULL);

	if(now == (time_t)-1)
	{
		return -1;
	}

	t = localtime(&now);

	if(t == NULL)
	{
		return -1;
	}

	len = sizeof(data->time);
	memset(data->time, 0, len);
	result = strftime(data->time, len, "%Y-%m-%d %H:%M:%S", t);

	if(result == 0)
	{
		return -1;
	}
	times = now;

	return times;
}


void get_data(data_t *data)
{
	get_temper(data);
	get_time(data);
	return ;
}


int pack_data(data_t *data, uint8_t *buf, int len)
{
	int			rv = -1;

	if( !data )
	{   
		log_error("%s() Invalid input arguments\n", __func__);
		return -1;
	}   

	memset(buf, 0, len);
	rv = snprintf(buf, len, "ID=%s\nTIME=%s\nTEMPERATURE=%.4f\n", data->sn, data->time, data->temper);

	return rv;
}


int pack_data_json(data_t *data, uint8_t *buf, int len)
{
	int			rv;

	if( !data )
	{   
		log_error("%s() Invalid input arguments\n", __func__);
		return -1;
	}

	memset(buf, 0, len);
	snprintf(buf, len, "{\"ID\":\"%s\", \"TIME\":\"%s\",\"TEMPERATURE\":\"%.4f\"}", data->sn, data->time, data->temper);

	rv = strlen(buf);

	return rv;
}


int pack_data_tlv(data_t *data, uint8_t *buf, int len)
{
	int					offset = 0;
	uint16_t			crc;
	char 				*time_str = data->time;
	int					year, month, day, hour, minute, second;
	int					tag_temp = 1;

	if( !data )
	{
		log_error("%s() Invalid input arguments\n", __func__);
		return -1;
	}

	memset(buf, 0, len);


	*(uint16_t *)buf = htons(0xFEDD);
	offset += 2;


	buf[offset] = tag_temp;
	offset += 1;		
	offset += 2;		

	strncpy((char *)(buf+offset), data->sn, 10);
	offset += 10;


	sscanf(time_str, "%4d%2d%2d %2d:%2d:%2d", &year, &month, &day, &hour, &minute, &second);
	buf[offset++] = (uint8_t)(year - 2000);
	buf[offset++] = (uint8_t)month;
	buf[offset++] = (uint8_t)day;
	buf[offset++] = (uint8_t)hour;
	buf[offset++] = (uint8_t)minute;
	buf[offset++] = (uint8_t)second;


	buf[offset++] = (int)data->temper;		
	buf[offset++] = ( ( ((int)(data->temper*10000)) % 10000 ) / 100 );		//小数部分1
	buf[offset++] = ( ( ((int)(data->temper*10000)) % 10000 ) % 100 );		//小数部分2


	*(uint16_t *)(buf+3) = (offset-5);


	crc = crc_itu_t(buf, offset);
	*(uint16_t *)(buf+offset) = htons(crc);
	offset += 2;

	return offset;
}


/*计算数据的CRC-ITU-T校验值*/
static uint16_t crc_itu_t(const uint8_t *data, size_t length)
{
	uint16_t          crc = 0xFFFF;
	size_t            i, j;

	for (i=0; i<length; i++)
	{
		crc ^= ((uint16_t)data[i] << 8);

		for(j=0; j<8; j++)
		{
			if (crc & 0x8000)
			{
				crc = (crc << 1) ^ CRC16_ITU_T_POLY;
			}
			else
			{
				crc <<= 1;
			}
		}
	}

	return crc;
}

